home *** CD-ROM | disk | FTP | other *** search
- /* Generated by Interface Builder */
-
- #import "ClassManager.h"
- #import "MenuManager.h"
- #import "NuString.h"
- #import "PrefsManager.h"
- #import "FinderManager.h"
- #import <appkit/Application.h>
- #import <appkit/Text.h>
- #import <appkit/Panel.h>
- #import <appkit/NXBrowser.h>
- #import <appkit/NXBrowserCell.h>
- #import <defaults/defaults.h>
- #import <appkit/NXSplitView.h>
- #import <appkit/Matrix.h>
- #import <objc/objc-load.h>
- // #import <objc/objc-runtime.h> // causes compiler errors in 3.0!
- #import <objc/Storage.h>
- #import <objc/List.h>
- #import <streams/streams.h>
- #import <libc.h>
- #import <strings.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #import "GlyphView.h"
- #import <regex.h>
-
- extern id Nu ;
- extern void NuGets(NXStream *aStream, char * aBuf) ;
- static id loadList ; // this global var points to a list of
- // NuStrings containing
- // the classnames of every loaded class
-
- id classWinList ; // this global var contains a list of the id's of all
- // currently open class windows
-
-
- @implementation ClassManager: WorkspaceManager
-
- int superClassName(char *filePath, char *superClass)
- { // assumes filePath is the path to a .o file
- // containing a class definition. Sets superClass
- // to the name of its superclass. Returns 1 if
- // successful, else 0.
- struct mach_header mh ;
- struct segment_command sc ;
- struct section sect ;
- struct objc_class oc ;
- int fn, i,j ;
- char c ;
- if((fn = open(filePath, O_RDONLY)) < 0)
- return 0 ;
- lseek(fn, 0l, 0) ;
- if(read(fn,&mh,sizeof(struct mach_header)) < sizeof(struct mach_header))
- return 0 ; // short file
- for(i = 0 ; i < mh.ncmds ; i++) // for each load command
- { if(read(fn,&sc,sizeof(struct load_command)) < sizeof(struct load_command))
- return 0 ; // short file
- if(sc.cmd != LC_SEGMENT) // not a segment command, skip it
- if(lseek(fn, sc.cmdsize - sizeof(struct load_command) ,L_INCR) == -1)
- return 0 ; // can't seek
- else // segment command...get rest of header
- { if(read(fn,&sc.segname,sizeof(struct segment_command) -
- sizeof(struct load_command)) < sizeof(struct segment_command) -
- sizeof(struct load_command))
- return 0 ; // short file
- else
- { for(j = 0 ; j < sc.nsects ; j++) // for each segment header
- { if(read(fn,§,sizeof(struct section)) < sizeof(struct section))
- return 0 ; // short file ;
- if(!strcmp(sect.segname,"__OBJC") &&
- !strcmp(sect.sectname,"__class"))
- { // we've found the correct section and segment
- if(lseek(fn,sect.offset,L_SET) == -1)
- return 0 ; // can't seek
- if(read(fn,&oc,sizeof(struct objc_class))
- < sizeof(struct objc_class))
- return 0 ; // short file
- if(lseek(fn,mh.sizeofcmds + (long int) oc.super_class +
- sizeof(struct mach_header), L_SET) == -1)
- return 0 ; // can't seek
- i = 0 ;
- while(read(fn,&c,1))
- { superClass[i] = c ;
- if(!superClass[i++])
- { close(fn) ;
- return 1 ;
- }
- }
- }
- }
- }
- }
- }
- close(fn) ;
- return 0 ;
- }
-
- + compileClass:(char *) aClass file:(char *) aFile
- { // compile file aFile containing .m file for
- // class aClass. return nil on error.
- char buf[512] ;
- const char *rootPath ;
- char tmpFile[20] = "NuXXXXXX" ;
- int rval ;
- // use awk to create .h file
- mktemp(tmpFile) ;
- rootPath = NXGetDefaultValue([NXApp appName],"NuPath") ;
- sprintf(buf,
- "awk '\\\n"
- "/^#pragma .h/ { $1 = \"\";$2=\"\"; print}\\\n"
- "/^@implementation/ { if(state == 0) {$1 = \"@interface\"; print ;state++} }\\\n"
- "/^{/ { if(state == 1) state++ }\\\n"
- " { if(state == 2) print }\\\n"
- "/^}/ { if(state == 2) state++ }\\\n"
- "/^[+-]/ { if(state == 3) print }\\\n"
- "/^@end/ { print \"@end\" ; state = 0}'\\\n"
- " < %s > %s/.h/%s.h",
- aFile, rootPath, aClass ) ;
- system(buf) ;
- // compile into .o file ... don't remove the -c !
- sprintf(buf, "cc -c -I %s/.h %s -o %s/.o/%s.o %s"
- " 2> /tmp/%s",
- rootPath,
- NXGetDefaultValue([NXApp appName],"CompilerOptions"),
- rootPath, aClass, aFile, tmpFile) ;
- if(rval = system(buf)) // non-zero exit status == errors
- { sprintf(buf,"/tmp/%s",tmpFile) ;
- [Nu appendFileToTranscript: buf] ;
- NXRunAlertPanel("Nu","Compilation errors: see Transcript Window\n",
- NULL,NULL,NULL) ;
- }
- sprintf(buf,"rm /tmp/%s 2> /dev/null",tmpFile) ;
- system(buf) ;
- if(rval == 0)
- return self ;
- else
- return nil ;
- }
-
-
- + initialize ;
- // initialize the loadList
- { loadList = [List new] ;
- classWinList = [List new] ;
- return [super initialize] ;
- }
-
- +(BOOL) isLoaded: (char *) aClass ;
- // returns YES iff aClass is currently loaded.
- { NXHashTable *class_hash = objc_getClasses();
- NXHashState state = NXInitHashState(class_hash);
- Class class;
- while(NXNextHashState(class_hash, &state, (void **) &class))
- { if(!strcmp(class->name,aClass))
- return YES ;
- }
- return NO ;
- }
-
- + loadAll ;
- // loads all the classes on the loadList. This is
- // called when unarchiving: first the loadList is
- // established from the archive, then this method
- // is invoked to load all these classes. Returns
- // nil and unloads all classes if any class cannot
- // be loaded. Does not rebuild debug files
- { int i, knt, moduleKnt ;
- char buf[512] ;
- id linkList ;
- if(!loadList) // loadList not initialized == nothing to load
- return nil ;
- knt = [loadList count] ;
- linkList = [NXGetNamedObject("PrefsManager",NXApp) linkList] ;
- moduleKnt = [linkList count] ;
- { char *moduleNames[moduleKnt+2] ;
- for(i = 0 ; i < moduleKnt ; i++) // make list of libraries
- moduleNames[i+1] = (char *) [[linkList objectAt: i] cString] ;
- moduleNames[i+1] = NULL ; // terminate the list
- for(i = 0 ; i < knt ; i++)
- { sprintf(buf,"%s/%s.o",NXGetDefaultValue([NXApp appName],"NuPath"),
- [[loadList objectAt: i] cString]) ;
- moduleNames[0] = buf ;
- if(objc_loadModules(moduleNames, NULL, NULL, NULL,NULL))
- { NXRunAlertPanel("Nu","Error in loading, no classes loaded",
- NULL,NULL,NULL) ;
- [self unloadAll] ;
- return self ;
- }
- }
- }
- return self ;
- }
-
- +(int) loadIndex: (const char *) nameOfClass ;
- // if nameOfClass is in the load list, return its index,
- // else return -1. The load list is a list of
- // all classes which have been dynamically loaded.
- { int i, knt ;
- knt = [loadList count] ;
- for(i = 0 ; i < knt ; i++)
- { if(!strcmp([[loadList objectAt: i] cString], (char *) nameOfClass))
- return i ;
- }
- return -1 ;
- }
-
- + loadList ;
- { return loadList ;
- }
-
- + loadList: aList ;
- { loadList = aList ;
- return self ;
- }
-
- + load: (const char *) aClass ;
- { // returns nil if aClass can't be loaded
- int i, loadIndex, knt ;
- id nmList, oldIdList, newIdList, gVList ;
- char *ptr ;
- id placeHolder, rval ;
- rval = self ;
- nmList = [[List alloc] init] ;
- oldIdList = [[List alloc] init] ;
- newIdList = [[List alloc] init] ;
- gVList = [[List alloc] init] ;
- placeHolder = [[Object alloc] init] ;
- if((loadIndex = [self loadIndex: aClass]) == -1)
- { // not loaded ;
- [oldIdList addObject: placeHolder] ; // don't know id yet...
- [nmList addObject: [NuString new: (char *) aClass]] ;
- }
- else
- { // must unload it, and classes loaded 'after' it
- knt = [loadList count] ;
- for(i = loadIndex ; i < knt ; i++)
- { ptr = (char *) [[loadList objectAt: i] cString] ;
- [oldIdList addObject:objc_getClass(ptr)] ;
- [nmList addObject:[NuString new: ptr]] ;
- }
- for(i = loadIndex ; i < knt ; i++)
- { objc_unloadModules(NULL,NULL) ;
- [[loadList removeLastObject] free] ;
- }
- }
- knt = [oldIdList count] ;
- for(i = 0 ; i < knt ; i++)
- { ptr = (char *) [[nmList objectAt: i] cString] ;
- if(![self loadAux: ptr])
- { NXRunAlertPanel("Nu","Can't load: %s\n"
- "See Transcript for details.", NULL,NULL,NULL,ptr) ;
- rval = nil ;
- }
- else
- [newIdList addObject: objc_getClass(ptr)] ;
- }
- [GlyphView become:newIdList if:oldIdList views: gVList] ;
- [gVList makeObjectsPerform: @selector(display)] ;
- [nmList makeObjectsPerform: @selector(free)] ;
- [nmList free] ;
- [oldIdList free] ;
- [newIdList free] ;
- [gVList free] ;
- [placeHolder free] ;
- [[Nu loadedClassesBrowser] loadColumnZero] ;
- [[[Nu loadedClassesBrowser] matrixInColumn: 0]
- scrollCellToVisible:[loadList count] - 1 :0] ;
- return rval ;
- }
-
- + (BOOL) loadAux: (char *) aClass ;
- { // try to load aClass. Return YES iff successful,
- // else return NO.
- const char *baseFile ;
- char file[512], tempFile[512], superClass[256], *debugFile ;
- const char *theFlags ;
- NXStream *aStream ;
- int i, moduleKnt ;
- id linkList ;
- // see if class is "hard loaded"
- if([self isLoaded: aClass])
- return YES ;
- aStream = NXOpenMemory(NULL, 0, NX_READWRITE) ;
- baseFile = NXGetDefaultValue([NXApp appName],"NuPath") ;
- sprintf(file,"%s/.o/%s.o",baseFile,aClass);
- if(!superClassName(file,superClass))
- { [Nu printf: "Corrupt file: %s. Try recompiling it.\n", aClass] ;
- return NO ;
- }
- if([self loadIndex: superClass] == -1)
- { // superClass not loaded
- if(![self loadAux: superClass])
- { [Nu printf: "Couldn't load class %s, superclass of %s.\n",
- superClass, aClass] ;
- return NO ;
- }
- }
- linkList = [NXGetNamedObject("PrefsManager",NXApp) linkList] ;
- moduleKnt = [linkList count] ;
- theFlags = NXGetDefaultValue([NXApp appName],"Flags") ;
- if(theFlags[DEBUGFILES] - '0')
- { sprintf(tempFile,"%s/.g/%s.g",baseFile,aClass) ;
- debugFile = tempFile ;
- }
- else
- debugFile = NULL ;
- { char *modules[moduleKnt + 2] ;
- for(i = 0 ; i < moduleKnt ; i++)
- modules[i+1] = (char *) [[linkList objectAt: i] cString] ;
- modules[0] = file ;
- modules[i+1] = NULL ;
- if(!objc_loadModules(modules, aStream, NULL, NULL,debugFile))
- { [loadList addObject: [NuString new: aClass]] ;
- NXCloseMemory(aStream,NX_TRUNCATEBUFFER) ;
- return YES ;
- }
- else // load failed
- { char *textBuf ;
- int textLen, maxLen ;
- NXGetMemoryBuffer(aStream, &textBuf, &textLen, &maxLen);
- [Nu printf: "%s\n", textBuf] ;
- NXCloseMemory(aStream,NX_TRUNCATEBUFFER) ;
- return NO ;
- }
- }
- }
-
-
- + unload: (const char *) aClass ;
- { // unload aClass if it was incrementally loaded.
- // returns nil if unable. Disallow unloading
- // the "system" classes "Root","Glyph", "Tray",
- // and "Error".
- volatile List *nmList,*oldIdList, *newIdList, *gVList ;
- volatile char *ptr ;
- volatile id placeHolder, rval, rG ;
- volatile int i , ind , knt ;
- volatile NXRect aRect ;
- if(!strcmp(aClass,"Glyph") || !strcmp(aClass,"Root")
- || !strcmp(aClass,"Tray") || !strcmp(aClass,"Error"))
- { NXRunAlertPanel("Nu","Error: you cannot unload class %s,\n"
- "though you may edit, recompile, and reload it.",
- NULL,NULL,NULL,aClass) ;
- return self ;
- }
- rval = self ;
- nmList = [List new] ;
- oldIdList = [List new] ;
- newIdList = [List new] ;
- gVList = [List new] ;
- placeHolder = [Object new] ;
- ind = [self loadIndex: aClass] ;
- if(ind == -1)
- return nil ;
- else
- { // must unload it, and classes loaded 'after' it
- knt = [loadList count] ;
- for(i = ind ; i < knt ; i++)
- { [oldIdList addObject: objc_getClass((char *)[[loadList objectAt: i] cString])] ;
- if(i == ind) // Will change existing aClass instances into Error glyphs
- [nmList addObject: [NuString new: "Error"]] ;
- else
- [nmList addObject: [NuString new: (char *) [[loadList objectAt: i] cString]]] ;
- }
- for(i = ind ; i < knt ; i++)
- { objc_unloadModules(NULL,NULL) ;
- [[loadList removeLastObject] free] ;
- }
- }
- knt = [oldIdList count] ;
- for(i = knt - 1 ; i >= 0 ; i--)
- { ptr = (char *) [[nmList objectAt: i] cString] ;
- if(![self loadAux: ptr])
- { NXRunAlertPanel("Nu","Can't load: %s\n"
- "See Transcript for details.", NULL,NULL,NULL,ptr) ;
- rval = nil ;
- }
- else
- [newIdList insertObject: objc_getClass((char *) [[nmList objectAt: i] cString]) at: 0] ;
- }
- [GlyphView become:newIdList if:oldIdList views: gVList] ;
- // redisplay all glyphViews which have glyph classes which have changed
- knt = [gVList count] ;
- for(i = 0 ; i < knt ; i++)
- { rG = [[gVList objectAt: i] rootGlyph] ;
- [rG getFrame: &aRect] ;
- [rG display: &aRect from: nil] ;
- }
- [gVList makeObjectsPerform: @selector(display)] ;
- [gVList free] ;
- [nmList makeObjectsPerform: @selector(free)] ;
- [nmList free] ;
- [oldIdList free] ;
- [placeHolder free] ;
- [[Nu loadedClassesBrowser] loadColumnZero] ;
- return rval ;
- }
-
- + unloadAll ;
- // unload all incrementally loaded classes, except the
- // "system" classes, which will always be the bottom 4.
- { int i, loadKnt ;
- loadKnt = [loadList count] ;
- for(i = 0 ; i < loadKnt - 4 ; i++)
- { [[loadList lastObject] free] ;
- [loadList removeLastObject] ;
- objc_unloadModules(NULL,NULL) ;
- }
- [[Nu loadedClassesBrowser] loadColumnZero] ;
- return self ;
- }
-
- +winList ;
- { return classWinList ;
- }
-
-
- - (int)browser:sender fillMatrix:matrix inColumn:(int)column ;
- { if(msgList)
- return [msgList count] ;
- else
- return 0 ;
- }
-
- - browser:sender loadCell:cell atRow:(int)row inColumn:(int)column ;
- { [cell setStringValue: [[msgList objectAt: row] cString]] ;
- [cell setLeaf: YES] ;
- return self ;
- }
-
-
- - className: (char *) name ;
- { // copy className into ivar
- strncpy(className, name, 63) ;
- return self ;
- }
-
-
- - classText: (char *) theText ;
- { // copy theText into text object
- [textView setText: theText] ;
- [self setDocEdited:YES];
- return self ;
- }
-
- - compile:sender ;
- { // returns nil if any errors
- id rval ;
- if([self isDocEdited]) // be sure file is saved first
- [self save: self] ;
- [self message: "Compiling..."] ;
- rval = [ClassManager compileClass: className file: fileName] ;
- [self message: ""] ;
- return rval ;
- }
-
-
- - editSuperClass: sender ;
- { // attempt to open this class's superclass definition
- char superClass[256] ;
- char path[2048] ;
- struct stat statBuf ;
- // can't edit superclass of class Glyph!
- if(!strcmp(className,"Glyph"))
- { NXRunAlertPanel("Nu",
- "Error: can't edit class Object,\n"
- "superclass of class Glyph\n",
- NULL,NULL,NULL) ;
- return nil ;
- }
- // create path to my .o file
- sprintf(path,"%s/.o/%s.o",
- NXGetDefaultValue([NXApp appName],"NuPath"),className) ;
- // verify the path
- if(stat(path,&statBuf))
- { NXRunAlertPanel("Nu",
- "Error: can't find binary for class %s\n"
- "Have you compiled it?",
- NULL,NULL,NULL,className) ;
- return nil ;
- }
- // get the superclass's name
- if(!superClassName(path, &superClass[0]))
- { NXRunAlertPanel("Nu",
- "Error: can't determine superclass of %s\n"
- "Try recompiling %s",
- NULL,NULL,NULL,className, className) ;
- return nil ;
- }
- // (attempt to) edit the superclass
- if(![[Nu glyphManager] editFile: nil class: superClass])
- { NXRunAlertPanel("Nu",
- "Error: can't edit class %s,\n"
- "superclass of %s. Is it compiled?",
- NULL,NULL,NULL,className, superClass) ;
- return nil ;
- }
- return self ;
- }
-
- - (char *) extension ;
- { // provide file extension
- return "m" ;
- }
-
- - format: sender ;
- { // format my text and update the browser
- char textBuf[256], quotedBuf[513] ;
- char *c, *d, fontStuff[5][5][40], defName[12] ;
- const char *defaults ;
- int i, len, charNum ;
- NXStream *rawStream, *cookedStream ;
- [msgList freeObjects] ;
- rawStream = [textView stream] ;
- cookedStream = NXOpenMemory(NULL,0,NX_READWRITE) ;
- NXPrintf(cookedStream,
- "{\\rtf0\\ansi{\\fonttbl") ;
- // get the font information from defaults database
- for(i = 0 ; i < 5 ; i++)
- { // Manufacture default name
- sprintf(defName,"classText%1d",i) ;
- defaults = NXGetDefaultValue([NXApp appName],defName) ;
- // parse the default value
- sscanf(defaults,"%s %s %s %s %s %s",
- textBuf, fontStuff[i][0], fontStuff[i][1],
- fontStuff[i][2],fontStuff[i][3], fontStuff[i][4]) ;
- NXPrintf(cookedStream,"\\f%1d\\fnil %s;", i,textBuf) ;
- }
- NXPrintf(cookedStream,"}\n") ;
- NXPrintf(cookedStream,"{\\colortbl") ;
- for(i = 0 ; i < 5 ; i++)
- { NXPrintf(cookedStream,fontStuff[i][1]) ;
- NXPrintf(cookedStream,";") ;
- }
- NXPrintf(cookedStream,"}\n") ;
-
- charNum = 0 ;
- do
- { NXSeek(rawStream, charNum, NX_FROMSTART) ;
- NuGets(rawStream,textBuf) ;
- for(c = textBuf, d = quotedBuf ; *c ;)
- { if(*c == '{' || *c == '}' || *c == '\\' || *c == '-' || *c == '\n')
- { // must quote these chars for rtf
- *d++ = '\\' ;
- }
- if(*c == '/' && *(c+1) == '/')
- { char tempStr[256] ;
- // change style for slash-slash comment
- sprintf(tempStr,"\\f3%s\\cf3%s%s%s",
- fontStuff[3][0],fontStuff[3][2],
- fontStuff[3][3], fontStuff[3][4]) ;
- strcpy(d,tempStr) ;
- (int) d += strlen(tempStr) ;
- }
- *d++ = *c++ ;
- }
- *d = '\0' ;
- switch(textBuf[0])
- { case '#': i = 0 ; break ;
- case '@': i = 1 ; break ;
- case '/':
- case '-':
- case '+': i = 2 ; break ;
- default : i = 4 ; break ;
- }
- NXPrintf(cookedStream,
- "\\f%1d%s\\cf%1d%s%s%s %s", i,
- fontStuff[i][0], i,fontStuff[i][2],
- fontStuff[i][3],fontStuff[i][4],quotedBuf) ;
- if(i == 1 || i == 2) // add to msgList
- [msgList addObject: [NuString new: textBuf]] ;
- len = strlen(textBuf) ;
- charNum += len ; // don't forget the newline
- } while(!NXAtEOS(rawStream)) ;
- NXSeek(cookedStream, 0, NX_FROMSTART) ;
- /* uncomment to print stream to transcript
- { char *a ;
- int t,m ;
- NXGetMemoryBuffer(cookedStream, &a, &t, &m);
- [Nu printf: a] ;
- }
- */
- [textView readRichText: cookedStream] ;
- NXCloseMemory(cookedStream,NX_TRUNCATEBUFFER) ;
- [msgBrowser loadColumnZero] ;
- return self ;
- }
-
- - free ;
- { [msgList freeObjects] ;
- [msgList free] ;
- return [super free] ;
- }
-
- - goToMsg: sender ;
- { // sender is a cell in the msgBrowser ; find
- // the text in the textView
- id manager ;
- manager = NXGetNamedObject("FinderManager",NXApp) ;
- if(manager) // should always be true
- { [manager find: (char *)
- [[[sender matrixInColumn: 0] selectedCell]stringValue]
- regEx: NO caseSensitive: YES inSelection: NO] ;
- }
- return self ;
- }
-
- - init ;
- { // add my id to the classWinList
- [super init] ;
- [classWinList addObject: self] ;
- // assemble the pieces we get from the nib
- [msgBrowser useScrollButtons: YES] ;
- [splitView addSubview: [msgBrowser removeFromSuperview]] ;
- [splitView addSubview: [[[textView superview] superview]
- removeFromSuperview]] ;
- // make sure we are not monofont
- [self setMiniwindowIcon: "cmIcon.tiff"] ;
- // create Storage for line numbers of
- // lines in the msgBrowser
- msgList = [List new] ;
- return self ;
- }
-
-
- - load:sender ;
- { [self message: "Loading..."] ;
- [ClassManager load:className] ;
- [self message: ""] ;
- return self ;
- }
-
- - (const char *) name ;
- { // redefine so that I can easily
- // be identified
- return className ;
- }
-
- - readFile ;
- { NXStream *fileStream ;
- if(fileName[0] == '\0')
- return self ; // no file to read!
- [self message: "Reading file..."] ;
- if((fileStream = NXMapFile(fileName,NX_READONLY)) != NULL)
- { [textView readText: fileStream] ;
- NXCloseMemory(fileStream,NX_FREEBUFFER);
- [self format: self] ;
- [self setDocEdited: NO] ;
- }
- else
- NXRunAlertPanel("Nu", "Error, couldn't read: %s",
- NULL,NULL,NULL,fileName) ;
- [self message: ""] ;
- return self ;
- }
-
-
- -(BOOL) saveTextToFileName ;
- // pre: -ivar fileName contains a valid
- // file pathname.
- // -ivar textView contains a TextView object
- // post: if file can be opened or created, with mode
- // 644: text of textView is written out to the
- // file named by fileName; file is closed, and
- // YES is returned.
- // otherwise returns NO
- { NXStream *aStream ;
- [self message: "Saving file..."] ;
- aStream = NXOpenMemory(NULL,0, NX_WRITEONLY);
- [textView writeText:aStream];
- NXSaveToFile(aStream, fileName);
- NXCloseMemory(aStream, NX_FREEBUFFER);
- [self setDocEdited:NO];
- [self message: ""] ;
- return YES ;
- }
-
- - update: sender ;
- { // save if needed, compile if needed, load if needed
- struct stat mStat,oStat ;
- const char *rootPath ;
- char comBuf[512] ;
- rootPath = NXGetDefaultValue([NXApp appName],"NuPath") ;
- if([self isDocEdited]) // be sure file is saved first
- [self save: self] ;
- stat(fileName,&mStat) ;
- sprintf(comBuf,"%s/.o/%s.o",rootPath,className) ;
- if(stat(comBuf,&oStat) || (mStat.st_mtime >= oStat.st_mtime))
- { // no .o file or .o out of date
- if([self compile: self])
- [self load: self] ;
- }
- else if([ClassManager loadIndex: className] == -1)
- [self load: self] ;
- return self ;
- }
-
- - windowWillClose: sender ;
- { // remove myself from the classWinList
- [classWinList removeObject: self] ;
- return self ;
- }
-
- - read: (NXTypedStream *) aStream ;
- { [super read: aStream] ;
- NXReadArray(aStream, "c", 64, className) ;
- return self ;
- }
-
- - write: (NXTypedStream *) aStream ;
- { [super write: aStream ] ;
- NXWriteArray(aStream, "c", 64, className) ;
- return self ;
- }
-
- @end
-